package com.jiyongjun.component.sls;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.aliyun.log.producer.Producer;
import com.aliyun.openservices.log.common.LogItem;
import com.jiyongjun.component.config.LogBootstrapConfig;
import com.jiyongjun.component.core.model.BaseLogContext;
import com.jiyongjun.component.utils.JsonUtils;
import com.jiyongjun.component.utils.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

/**
 * <h2></h2>
 * <h3>描述：</h3>
 *
 * @author yongjun.jyj
 * @since 2022/7/14 18:27
 */
@Service
@Slf4j
public class SlsLogService implements InitializingBean {
    @Qualifier("logSlsProducer")
    @Autowired
    private Producer slsProducer;

    @Autowired
    private LogBootstrapConfig logBootstrapConfig;

    private Map<Class<?>, Set<String>> FIELD_MAP = new HashMap();

    private static SlsLogService INSTANCE;

    @Override
    public void afterPropertiesSet() throws Exception {
        INSTANCE = SpringContextHolder.getBeanWithCache(SlsLogService.class);
    }

    public static SlsLogService getInstance() {
        return INSTANCE;
    }

    public <T> void log(T logObj) {
        LogItem logItem = new LogItem();
        Set<String> fields = FIELD_MAP.computeIfAbsent(logObj.getClass(), key -> {
            List<Field> fieldList = Arrays.stream(key.getDeclaredFields()).collect(toList());
            fieldList.addAll(Arrays.asList(key.getSuperclass().getDeclaredFields()));

            return fieldList.stream()
                    .filter(field -> !Modifier.isTransient(field.getModifiers()) && !Modifier.isStatic(field.getModifiers()))
                    .map(Field::getName)
                    .collect(toSet());
        });

        JSONObject jsonObject = JSON.parseObject(JsonUtils.toJson(logObj));

        // 分割字段
        jsonObject.forEach((key, val) -> {
            if (val == null || !fields.contains(key)) {
                return;
            }

            if (BaseLogContext.Fields.extInfoMap.equals(key)) {
                ((JSONObject) val).forEach((extKey, extVal) -> {
                    if (extVal == null) {
                        return;
                    }
                    logItem.PushBack(extKey, extVal.toString());
                });
            } else {
                logItem.PushBack(key, val.toString());
            }
        });

        try {
            slsProducer.send(logBootstrapConfig.getSlsProject(), logBootstrapConfig.getSlsLogStore(), logItem);
        } catch (Exception e) {
            log.error("日志发送异常|msg={}", e.getMessage(), e);
        }
    }

}
